<template lang="pug">
  div(style="width:100%")
    div(:id="richboxId" 
        ref="$$richbox" 
        :data-id="dataId" 
        @blur="onblur" 
        @focus="onfocus"
        class="awesome-richbox"
        @keyup.navite.enter="enter" )
    EmojiPicker(v-show="false" ref="emoji")
</template>

<script>
import EmojiPicker from "./EmojiPicker";
export default {
  name: "rich-box",
  components: { EmojiPicker },
  data() {
    return {
      richboxId: null,
      dataId: null,
      lastRange: null, // 最后的选中区域记录
      value: ""
    };
  },
  watch: {},
  methods: {
    /** 获取选中区域     */
    _getSelection() {
      const getSelection =
        window.getSelection || document.getSelection || body.getSelection;
      return getSelection();
    },
    /** 获取到selection的range对象 */
    _getRange() {
      const selection = this._getSelection();

      return new Promise((resolve, reject) => {
        if (!selection.rangeCount) {
          reject("no range"); // 如果没有选中，则
        }
        const range = selection.getRangeAt(0);
        resolve({ range, selection });
        return;
      });
      // --
    },
    // 判断元素是否在当前组件中
    _isIn(el) {
      if (el.getAttribute) {
        // 如果是text，则不会有getAttribute方法
        var dataId = el.getAttribute("data-id");
        if (dataId == this.dataId) return true;
      }

      if (!el.parentElement) return false;
      return this._isIn(el.parentElement);
    },
    /**
     * 根据lastRange创建选中区域(默认的focus会把光标放在首位，但应该放在末尾)
     */
    focus() {
      const self = this.$refs.$$richbox;
      self.focus();

      const selection = this._getSelection();

      const newRange = document.createRange();
      newRange.selectNodeContents(self);
      newRange.collapse(false); // 为了光标定位在最后
      selection.removeAllRanges();
      selection.addRange(newRange);
    },
    /**
     * 恢复上次的选择区域
     */
    restoreRange() {
      if (!this.lastRange) return;
      const selection = this._getSelection();
      selection.removeAllRanges();
      selection.addRange(this.lastRange);
    },
    /**
     * 光标或选中区域插入元素 调用者自行组装element
     */
    insertElement(element) {
      var vm = this;
      const selection = this._getSelection();

      // 没有选中区域（range）
      if (!selection.rangeCount && !vm.lastRange) {
        this.$refs.$$richbox.appendChild(element);
        return;
      }

      let range = selection.rangeCount ? selection.getRangeAt(0) : vm.lastRange;
      const isIn = vm._isIn(range.commonAncestorContainer);

      if (isIn) {
        const dataId =
          range.commonAncestorContainer.nodeName == "#text" // 文本 则视为dataId等于dataId
            ? this.dataId
            : range.commonAncestorContainer.getAttribute("data-id");

        if (dataId && dataId == this.dataId) {
          range.deleteContents();
          range.insertNode(element);
        } else {
          var newRange = document.createRange();
          newRange.setStartAfter(range.commonAncestorContainer); // 如果range是个dom，则重新创建range，保证插入的node在richbox根目录下
          newRange.deleteContents();
          newRange.insertNode(element);
        }
        // -
      } else if (vm.lastRange) {
        const _newRange = document.createRange();
        range.setStartAfter(vm.lastRange.commonAncestorContainer); // 如果range是个dom，则重新创建range，保证插入的node在richbox根目录下
        // const _newRange = vm.lastRange;
        selection.removeAllRanges();
        selection.addRange(_newRange);
        _newRange.insertNode(element);
        // -
      } else {
        this.$refs.$$richbox.appendChild(element);
        return;
        // -
      }
      //-

      // 创建选中区域创建焦点
      const newRange = document.createRange();
      newRange.setStartAfter(element);

      this.lastRange = newRange; // 记录
      selection.addRange(newRange);
      selection.removeAllRanges();

      // --
    },
    /**
     * 光标或选中区域插入文本
     */
    insertText(text) {
      const spanEl = document.createElement("span");
      spanEl.innerText = text;
      spanEl.classList = (spanEl.classList || []).push("aw-span");
      this.insertElement(spanEl);
    },
    /**
     * 生产随机字符串
     */
    newID(len) {
      var s = "";
      while (s.length < len && len > 0) {
        var r = Math.random();
        s += String.fromCharCode(Math.floor(r * 26) + (r > 0.5 ? 97 : 65));
      }
      return s;
    },
    onblur() {
      var vm = this;
      this._getRange().then(({ range, selection }) => {
        // 记录range位置
        // vm.lastRange = range.cloneRange();
      });
      this.$emit("blur");
    },
    onfocus() {
      this.$emit("focus");
    },
    // 回车事件
    enter() {
      this.$emit("enter");
    },
    getHtmlContent() {
      return this.$refs.$$richbox.innerHTML;
    },
    getContent() {
      let htmlContent = this.$refs.$$richbox.innerHTML;
      const emojiNodes = this.$refs.$$richbox.getElementsByClassName(
        "aw-emoji"
      );
      for (let i = 0; i < emojiNodes.length; i++) {
        const node = emojiNodes[i];
        const val = "[:" + node.getAttribute("title") + ":]";
        htmlContent = htmlContent.replace(node.outerHTML, val);
      }
      return htmlContent;
    },
    setContent(content) {
      content = this.content2HtmlContent(content);
      this.$refs.$$richbox.innerHTML = content;
    },
    content2HtmlContent(content) {
      var mList = content.match(/\[\:(?<val>[\w|0-9]+)?\:\]/gi);
      if (!mList) return content;
      
      for (let i = 0; i < mList.length; i++) {
        const m = mList[i];
        const val = m.replace(/(\[\:)|(\:\])/gi, "");
        const node = this.$refs.emoji.resolve(val);
        if (!node) continue;
        content = content.replace(m, node.outerHTML.toString());
      }
      
      return content;
    }
  },
  mounted() {
    this.$refs.$$richbox.contentEditable = true; // 设置为可编辑
    this.dataId = this.newID(5);
  }
};
</script>

<style lang="less" scoped>
*,
*::before,
*::after {
  box-sizing: border-box;
}
.awesome-richbox {
  border: 1px solid #cccccc;
  padding: 3px 5px;
  width: 100%;
  background-color: white;
  min-height: 32px;
  line-height: 32px;
}
</style>
